package com.zheng.coderepo.redis;

import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 频率表达式。由次数/时间+时间单位组成。如:3/1s
 * Created by zhangchaozheng on 16-7-28.
 */
public class FrequencyExpr {

    private static final Pattern PATTERN_RATE_LIMITATION = Pattern.compile("(\\d+)/(\\d*)([smhd])");

    private int rate;

    private int durationSeconds;

    /**
     * 解析频率表达式。表达式由：次数/时间+时间单位组成。
     * 支持的单位为：秒、分、时、天。
     * <li>如：5/1m表示，每分钟5次。<li/>
     * <li>如：10/1s表示，每秒钟10次。<li/>
     *
     * @param expression 表达式
     * @return
     */
    public static FrequencyExpr parseLimitation(String expression) {
        if (expression == null) {
            throw new RuntimeException("Frequency expression should not be null.");
        }

        Matcher matcher = PATTERN_RATE_LIMITATION.matcher(expression);
        if (matcher.matches()) {
            FrequencyExpr limitation = new FrequencyExpr();
            limitation.setRate(Integer.parseInt(matcher.group(1)));
            int duration = 1;
            if (matcher.group(2).length() != 0) {
                duration = Integer.parseInt(matcher.group(2));
            }
            TimeUnit unit = null;
            switch (matcher.group(3).charAt(0)) {
                case 's':
                    unit = TimeUnit.SECONDS;
                    break;
                case 'm':
                    unit = TimeUnit.MINUTES;
                    break;
                case 'h':
                    unit = TimeUnit.HOURS;
                    break;
                case 'd':
                    unit = TimeUnit.DAYS;
                    break;
                default:
                    throw new RuntimeException("Unknown time unit: " + matcher.group(3));
            }
            limitation.setDurationUnit(duration, unit);
            return limitation;
        } else {
            throw new RuntimeException("Unknown frequency expression : " + expression);
        }
    }

    private void setDurationUnit(int duration, TimeUnit unit) {
        this.durationSeconds = (int) TimeUnit.SECONDS.convert(duration, unit);
    }

    public int getRate() {
        return rate;
    }

    public void setRate(int rate) {
        this.rate = rate;
    }

    public int getDurationSeconds() {
        return durationSeconds;
    }

    public void setDurationSeconds(int durationSeconds) {
        this.durationSeconds = durationSeconds;
    }
}
